package com.logistics.utils.aspect.impl;

import com.logistics.account.entity.model.AccountRow;
import com.logistics.account.service.AccountService;
import com.logistics.dictionary.entity.model.DictionaryRow;
import com.logistics.dictionary.service.DictionaryService;
import com.logistics.utils.aspect.annotation.Dictionary;
import com.logistics.utils.tool.StringUtils;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Aspect
@Order(-1)
@Component
public class PagerAspect {

    @Autowired
    private AccountService accountService;

    @Autowired
    private DictionaryService dictionaryService;


    @Pointcut("@annotation(com.logistics.utils.aspect.annotation.Pager)")
    public void listerPager(){
    }

    /**
     * 返回页面之前做字典和创建人修改人数据转换
     * @param result
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    @AfterReturning(pointcut = "listerPager()", returning = "result")
    public void afterPager(Object result) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        List<AccountRow> userInfo = accountService.accountAll();
        List<DictionaryRow> dictionaryRows = dictionaryService.allList();
        List<Object> rows = (List<Object>) getMethod(result.getClass(), "getRows").invoke(result, null);
        dataFormatter(rows, userInfo, dictionaryRows);
    }

    /**
     * 数据转换
     * @param rows
     * @param userInfo
     * @return
     */
    private void dataFormatter(List<Object> rows, List<AccountRow> userInfo, List<DictionaryRow> dictionaryRows){
        if(StringUtils.isNotNull(rows)){
            rows.stream().forEach(item -> {
                try {
                    creatorFormatter(item, userInfo);
                    updaterFormatter(item, userInfo);
                    dictionaryFormatter(item, dictionaryRows);
                    Method method = getMethod(item.getClass(), "getChildren");
                    if(StringUtils.isNotNull(method)){
                        List<Object> children = (List<Object>) method.invoke(item, null);
                        if(StringUtils.isNotNull(children))
                            dataFormatter(children, userInfo, dictionaryRows);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    /**
     * 创建人转换
     * @param item
     * @param rows
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    protected  void creatorFormatter(Object item, List<AccountRow> rows) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object creator = getMethod(item.getClass(), "getCreator").invoke(item, null);
        if(StringUtils.isNotNull(creator)){
            String userName = rows.stream().filter(e -> StringUtils.isEquals(creator.toString(),
                    e.getCode())).map(e -> e.getUserName()).collect(Collectors.joining());
            setMethod(item, "setCreator", userName , String.class);
        }
    }


    /**
     * 修改人转换
     * @param item
     * @param rows
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    protected void updaterFormatter(Object item, List<AccountRow> rows) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object updater = getMethod(item.getClass(), "getUpdater").invoke(item, null);
        if(StringUtils.isNotNull(updater) && rows.size() > 0){
            String userName = rows.stream().filter(e -> StringUtils.isEquals(updater.toString(),
                    e.getCode())).map(e -> e.getUserName()).collect(Collectors.joining());
            setMethod(item, "setUpdater",userName, String.class);
        }
    }

    /**
     * 字典转换
     * @param item
     * @param rows
     */
    protected void dictionaryFormatter(Object item, List<DictionaryRow> rows){
        Arrays.stream(item.getClass().getDeclaredFields()).
                filter(e -> e.getAnnotation(Dictionary.class) != null).forEach(e -> {
            e.setAccessible(true);
            String key = e.getAnnotation(Dictionary.class).key();
            if(StringUtils.isNotNull(key)){
                rows.stream().filter(s -> StringUtils.isEquals(key, s.getCode())).forEach(s -> {
                    try {
                        Object value = e.get(item);
                        if(StringUtils.isNotNull(s.getChildren()) && StringUtils.isNotNull(value)){
                            String name = s.getChildren().stream().filter(t -> StringUtils.isEquals(t.getCode(), value.toString()))
                                    .map(t -> t.getName()).collect(Collectors.joining());
                            e.set(item, name);
                        }
                    } catch (IllegalAccessException e1) {
                        e1.printStackTrace();
                    }
                });
            }
        });
    }

    /**
     * 确定字段的情况下获取值
     * @param cls
     * @param methodName
     * @return
     * @throws NoSuchMethodException
     */
    protected Method getMethod(Class<?> cls, String methodName) {
        try {
            Method method = cls.getDeclaredMethod(methodName);
            method.setAccessible(true);
            return method;
        } catch (NoSuchMethodException e) {
            return null;
        }
    }

    /**
     * 确定字段的情况下设置值
     * @param object
     * @param methodName
     * @param value
     * @param type
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    protected void setMethod(Object object, String methodName, Object value,Class type) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<?> cls = object.getClass();
        Method method = cls.getDeclaredMethod(methodName, type);
        method.setAccessible(true);
        method.invoke(object, new Object[] { value });
    }
}
